package cn.layou.netty.test;

import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.util.ReferenceCountUtil;

/**
 * netty客户端
 *
 * @author layou
 * @date 2021-04-24
 */
public class NettyClient {
    public static void main(String[] args) throws InterruptedException {
        EventLoopGroup group = new NioEventLoopGroup(2);
        try {
            Bootstrap bootstrap = new Bootstrap();
            ChannelFuture f = bootstrap.group(group)
                    .channel(NioSocketChannel.class)
                    .handler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel socketChannel) throws Exception {
                            socketChannel.pipeline().addLast(new ChannelInboundHandlerAdapter() {
                                @Override
                                public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
                                    //打印接受到的消息
                                    ByteBuf buf = null;
                                    try {
                                        buf = (ByteBuf)msg;
                                        byte[] bytes = new byte[buf.readableBytes()];
                                        buf.getBytes(buf.readerIndex(), bytes);
                                        String result = new String(bytes);
                                        System.out.println(result);
                                    } finally {
                                        //没有调用writeAndFlush的时候需要手动释放内存，因为netty是绕过jvm直接操作内存的，这块内存不会被垃圾回收器回收
                                        if(null != buf) {
                                            ReferenceCountUtil.release(buf);
                                        }
                                    }
                                }

                                @Override
                                public void channelActive(ChannelHandlerContext ctx) throws Exception {
                                    //channel第一次连接上给服务端写个hello world
                                    ByteBuf buf = Unpooled.copiedBuffer("hello world".getBytes());
                                    ctx.writeAndFlush(buf);
                                }

                                @Override
                                public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
                                    cause.printStackTrace();
                                    ctx.close();
                                }
                            });
                        }
                    })
                    .connect("localhost", 8888);
            f.sync();
            f.addListener(new ChannelFutureListener() {
                @Override
                public void operationComplete(ChannelFuture channelFuture) throws Exception {
                    if(channelFuture.isSuccess()) {
                        System.out.println("连接成功");
                    } else {
                        System.out.println("连接失败");
                    }
                }
            });

            //维持channel阻塞
            f.channel().closeFuture().sync();
        } finally {
            group.shutdownGracefully();
        }

    }
}
